using System.Collections.Generic;
using foundation.events;
using System;

namespace foundation
{
    public class BaseModel : MiniDispatcher
    {
        protected int priority = 0;
        public string key;
        public BaseModel(int priority = 0)
        {
            this.priority = 0;
            TAttribute.register(this, priority);
        }



        // protected object createFilterRuntime(object root, string id, string value)
        // {
        //     return null;
        // }

        /**

        */
        protected object filterRuntime(object root, object target, O1ConditionVO filter)
        {

            if (null != target)
            {
                if (null != filter)
                {

                    var id = Convert.ToString(filter.id);
                    var value = Convert.ToString(filter.value);

                    target = DataConvert.tryGetValue(target, id);
                    if (null != target)
                    {
                        target = DataConvert.tryGetValue(target, value);
                    }
                    if (null == target)
                    {

                        var method = this.GetType().GetMethod("createFilterRuntime");
                        if (null != method)
                        {
                            target = method.Invoke(this, new object[] { root, id, value });
                        }

                    }
                }
            }
            return target;
        }

        protected bool checkCondition(object root, object target, O1ConditionVO condition)
        {

            var id = condition.id;
            var opera = condition.opera;
            var value = Convert.ToDouble(condition.value);


            var _hadValue = DataConvert.tryGetValue(target, id);
            if (null == _hadValue) return false;

            var leftValue = Convert.ToDouble(_hadValue);

            switch (opera)
            {
                case ">":
                    return leftValue > value;
                case ">=":
                case "-=":
                    return leftValue >= value;
                case "<":
                    return leftValue < value;
                case "<=":
                    return leftValue <= value;
                case "==":
                    return leftValue == value;
                case "<>":
                case "!=":
                    return leftValue != value;
            }


            return false;
        }

        public O1CheckResultVO doCheckLimit(object root, O1LimitVO limit, object param = null)
        {
            object target = filterRuntime(root, DataConvert.tryGetValue(root, key), limit.filter);
            if (null == target) return new O1CheckResultVO(this, limit, target, limit.filter);
            foreach (var condition in limit.conditions)
            {
                var result = checkCondition(root, target, condition);
                if (!result) return new O1CheckResultVO(this, limit, target, condition);
            }

            return null;
        }


        protected ConditionItem createConditionItem(ConditionItem item, object root, object target, O1LimitVO limit, O1ConditionVO condition)
        {
            item.count = DataConvert.tryGetValue(target, condition.id);
            item.needcount = condition.value;
            return item;
        }


        public List<ConditionItem> getLimitRewards(object root, O1LimitVO limit)
        {
            List<ConditionItem> result = new List<ConditionItem>();

            object target = filterRuntime(root, DataConvert.tryGetValue(root, key), limit.filter);
            if (null == target) return null;

            foreach (var condition in limit.conditions)
            {
                // if (condition.opera == "+=")
                // {
                ConditionItem item = new ConditionItem();
                item.model = this;
                item.condition = condition;
                item.limit = limit;
                item.target = target;
                this.createConditionItem(item, root, target, limit, condition);
                result.Add(item);
                // }
            }

            return result;
        }

        public static Dictionary<string, BaseModel> models = new Dictionary<string, BaseModel>();
        public static O1CheckResultVO checkLimit(object root, List<O1LimitVO> limits, object param = null)
        {
            if (limits == null) return null;
            foreach (var limit in limits)
            {
                BaseModel model = null;
                models.TryGetValue(limit.module, out model);
                if (null != model)
                {
                    var result = model.doCheckLimit(root, limit, param);
                    if (null != result)
                    {
                        return result;
                    }
                }
            }
            return null;
        }


        public static List<ConditionItem> getLimitRewards(object root, List<O1LimitVO> limits)
        {
            List<ConditionItem> result = new List<ConditionItem>();

            foreach (var limit in limits)
            {
                BaseModel model = null;
                models.TryGetValue(limit.module, out model);
                if (null != model)
                {
                    var list = model.getLimitRewards(root, limit);
                    if (list.Count > 0)
                    {
                        result.InsertRange(result.Count, list);
                    }
                }
            }
            return result;

        }

    }
}